package com.strawcom.charmring.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.DashPathEffect;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.strawcom.charmring.App;
import com.strawcom.charmring.R;
import com.strawcom.charmring.util.ImageUtil;

/**
 * set exercise goals for yourself
 * 
 * @author WangPeng
 */
public class TargetSettingView extends View {

	private final float LEVEL_1 = 0.35f;
	private final float LEVEL_2 = 0.70f;

	private final Paint mPaint = new Paint();
	private final RectF rectF = new RectF();
	private final Path mPath = new Path();
	private LinearGradient linearGradient;
	private DashPathEffect effects1;
	private Typeface typeface;
	private int mWidth;
	private int mHeight;

	private int barPadding;
	private float padding; // common padding
	private float titleRoundSize;
	private float titleTextSize;
	private float settingTextSize;
	private float unitTextSize;
	private float tipTextSize;
	private float infoTextSize;
	private float titleWidth;
	private float titleHeight;
	private float tipLineHeight;
	private float infoContentWidth;
	private float iconWidth;
	private float progressTop;
	private float progressBottom;
	private float barRadius;
	private float barShadowWidth;
	private float barIndicatorHeight;

	private Bitmap bmpRainbow;
	private Bitmap bmpInfoIcon1, bmpInfoIcon2, bmpInfoIcon3;
	private String[] infos, tips;
	private String info = "";
	private Bitmap bmpInfo;

	private float percent; // current value [0 - 100]
	private int startValue, endValue;
	private String title, unit;
	
	private int value;

	public TargetSettingView(Context context) {
		this(context, null);
	}

	public TargetSettingView(Context context, AttributeSet attrs) {
		super(context, attrs);
		setLayerType(LAYER_TYPE_SOFTWARE, null);
		typeface = App.i().tfYouYuan;
	}

	public void setValueInfo(int value, String title, String unit, int startValue, int endValue) {
		this.percent = (value - startValue) * 1f / (endValue - startValue);
		this.title = title;
		this.unit = unit;
		this.startValue = startValue;
		this.endValue = endValue;
	}
	
	@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
	    int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
	    int heightSize = (int) (widthSize * 0.46f);  
	    setMeasuredDimension(widthSize, heightSize);  
	}  

	@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		mWidth = w;
		mHeight = h;

//		linearGradient = new LinearGradient(0, 0, mWidth, 0, new int[] { 0xff24e8da, 0xff73e085, 0xffc5d82e, 0xffdd971f, 0xffe44e23 },
//				new float[] { 0f, 0.25f, 0.5f, 0.75f, 1f }, TileMode.REPEAT);
		
		linearGradient = new LinearGradient(0, 0, mWidth, 0, new int[] { 0xff7dc0e5, 0xffa7a1bd, 0xffbb7a9b, 0xffc94879, 0xffd10464 },
				new float[] { 0f, 0.25f, 0.5f, 0.75f, 1f }, TileMode.REPEAT);
		
		effects1 = new DashPathEffect(new float[] { mWidth * 0.1f, mWidth * 0.01f }, 1);

		padding = mWidth * 0.04f;
		titleRoundSize = mWidth * 0.3f;
		titleTextSize = mWidth * 0.05f;
		settingTextSize = mWidth * 0.15f;
		unitTextSize = mWidth * 0.04f;
		tipTextSize = mWidth * 0.05f;
		infoTextSize = mWidth * 0.04f;
		titleWidth = mWidth * 0.38f;
		titleHeight = mWidth * 0.135f;
		tipLineHeight = mWidth * 0.0045f;
		barRadius = mWidth * 0.045f;
		barShadowWidth = barRadius * 0.05f;
		barIndicatorHeight = mWidth * 0.03f;

		barPadding = 20;

		progressTop = titleHeight + padding;
		progressBottom = mHeight - tipTextSize - padding;

		bmpRainbow = Bitmap.createBitmap(mWidth - barPadding * 2, (int) (barRadius * 0.66f), Config.ARGB_8888);
		mPaint.setStyle(Style.FILL);
		mPaint.setShader(linearGradient);
		Canvas canvas = new Canvas(bmpRainbow);
		canvas.drawRect(0, 0, bmpRainbow.getWidth(), bmpRainbow.getHeight(), mPaint);
		mPaint.setShader(null);

		iconWidth = mWidth * 0.03f;
		bmpInfoIcon1 = ImageUtil.decodeResource(getResources(), R.drawable.exercise_setting_1, (int) iconWidth, (int) iconWidth);
		bmpInfoIcon2 = ImageUtil.decodeResource(getResources(), R.drawable.exercise_setting_2, (int) iconWidth, (int) iconWidth);
		bmpInfoIcon3 = ImageUtil.decodeResource(getResources(), R.drawable.exercise_setting_3, (int) iconWidth, (int) iconWidth);

		infos = getResources().getStringArray(R.array.exercise_settings);
		tips = getResources().getStringArray(R.array.exercise_settings_tip);
	}

	@Override protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		final float mPercent = percent == 1 ? percent - 0.01f : percent;
		final int color = bmpRainbow.getPixel((int) (bmpRainbow.getWidth() * mPercent), 0);
		// draw title
		mPaint.reset();
		mPaint.setAntiAlias(true);
		mPaint.setColor(0xffff648e);
		rectF.set(0, 0, titleWidth, titleHeight);
		canvas.drawRoundRect(rectF, titleRoundSize, titleRoundSize, mPaint);
		mPaint.setTypeface(typeface);
		mPaint.setColor(0xffffffff);
		mPaint.setTextSize(titleTextSize);
		canvas.drawText(title, (titleWidth - calcTextOffset(title, mPaint)) / 2, (titleHeight + titleTextSize) / 2, mPaint);
		// draw value
		value = (int) (startValue + (endValue - startValue) * percent);
		mPaint.setColor(color);
		mPaint.setTextSize(settingTextSize);
		mPaint.setFakeBoldText(true);
		mPaint.setTypeface(null);
		canvas.drawText(String.valueOf(value), titleWidth + padding, titleHeight, mPaint);
		float valueWidth = calcTextOffset(String.valueOf(value), mPaint);
		mPaint.setFakeBoldText(false);
		mPaint.setTypeface(typeface);
		mPaint.setColor(0xff5e5e5e);
		mPaint.setTextSize(unitTextSize);
		canvas.drawText(unit, titleWidth + valueWidth + padding * 2, titleHeight, mPaint);
		// draw tip
		mPaint.setColor(0xff5e5e5e);
		mPaint.setTextSize(tipTextSize);
		canvas.drawText(tips[0], 0, mHeight, mPaint);
		canvas.drawText(tips[1], (mWidth - calcTextOffset(tips[1], mPaint)) / 2, mHeight, mPaint);
		canvas.drawText(tips[2], mWidth - calcTextOffset(tips[2], mPaint), mHeight, mPaint);
		mPaint.setPathEffect(effects1);
		mPaint.setColor(0xffaaaaaa);
		mPaint.setStrokeWidth(tipLineHeight);
//		canvas.drawLine(tipTextSize * 2 + padding / 2, mHeight - tipTextSize / 2, mWidth / 2 - tipTextSize - padding / 2, mHeight
//				- tipTextSize / 2, mPaint);
//		canvas.drawLine(mWidth / 2 + tipTextSize + padding / 2, mHeight - tipTextSize / 2, mWidth - tipTextSize * 2 - padding / 2, mHeight
//				- tipTextSize / 2, mPaint);
		mPaint.setPathEffect(null);
		// draw bar
		canvas.drawBitmap(bmpRainbow, barPadding, progressBottom - barRadius * 0.68f, mPaint);
		final float barCenter = barRadius + (mWidth - barRadius * 2) * percent;
		mPaint.setColor(0xffffffff);
		mPaint.setShadowLayer(barShadowWidth, 2, 8, 0xffcccccc);
		canvas.drawCircle(barCenter, progressBottom - barRadius / 2, barRadius, mPaint);
		mPaint.clearShadowLayer();
		mPaint.setStyle(Style.STROKE);
		mPaint.setStrokeWidth(1);
		mPaint.setColor(0xffaaaaaa);
		canvas.drawCircle(barCenter, progressBottom - barRadius / 2, barRadius, mPaint);
		// draw info
		mPaint.setStyle(Style.FILL);
		mPaint.setColor(color);
		mPath.reset();
		mPath.moveTo(barCenter, progressBottom - barRadius * 1.5f);
		mPath.lineTo(barCenter - barIndicatorHeight * 0.5f, progressBottom - barRadius * 1.5f - barIndicatorHeight * 1.2f);
		mPath.lineTo(barCenter + barIndicatorHeight * 0.5f, progressBottom - barRadius * 1.5f - barIndicatorHeight * 1.2f);
		mPath.close();
		canvas.drawPath(mPath, mPaint);

		mPaint.setTextSize(infoTextSize);
		if (percent < LEVEL_1) {
			info = infos[0];
			bmpInfo = bmpInfoIcon1;
		} else if (percent < LEVEL_2) {
			info = infos[1];
			bmpInfo = bmpInfoIcon2;
		} else {
			info = infos[2];
			bmpInfo = bmpInfoIcon3;
		}
		infoContentWidth = calcTextOffset(info, mPaint) + padding * 2 + iconWidth + padding * 0.3f;

		float infoLeft = barCenter - infoContentWidth / 2;
		if (infoLeft < 0) {
			infoLeft = 0;
		} else if (infoLeft > mWidth - infoContentWidth) {
			infoLeft = mWidth - infoContentWidth;
		}

		rectF.set(infoLeft, progressTop, infoLeft + infoContentWidth, progressBottom - barRadius * 1.5f - barIndicatorHeight);
		canvas.drawRoundRect(rectF, titleRoundSize, titleRoundSize, mPaint);
		mPaint.setColor(0xffffffff);
		canvas.drawText(info, infoLeft + padding, (progressTop + progressBottom - infoTextSize) / 2 - infoTextSize * 0.3f, mPaint);
		canvas.drawBitmap(bmpInfo, infoLeft + calcTextOffset(info, mPaint) + padding + padding * 0.3f,
				(progressTop + progressBottom - infoTextSize) / 2 - infoTextSize * 1.3f, mPaint);
	}

	private float calcTextOffset(String text, Paint paint) {
		float[] textWidths = new float[text.length()];
		paint.getTextWidths(text, textWidths);
		float textTotalWidth = 0;
		for (float f : textWidths) {
			textTotalWidth += f;
		}
		return textTotalWidth;
	}

	@Override public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			return isTouchBaby(event);
		case MotionEvent.ACTION_MOVE:
			percent = (event.getX() - barPadding) / (mWidth - 2 * padding);
			if (percent > 1) {
				percent = 1;
			} else if (percent < 0) {
				percent = 0;
			}
			invalidate();
			break;
		}
		return super.onTouchEvent(event);
	}

	private boolean isTouchBaby(MotionEvent event) {
		final float x = event.getX();
		final float y = event.getY();

		final float barCenter = barRadius + (mWidth - barRadius * 2) * percent;
		final float comfortableWrap = mWidth * 0.06f;

		if ((x > barCenter - barRadius - comfortableWrap && x < barCenter + barRadius + comfortableWrap)
				&& (y > progressBottom - barRadius * 1.5f - comfortableWrap && y < progressBottom - barRadius * 0.5f + comfortableWrap)) {
			return true;
		}
		return false;
	}
	
	public int getValue() {
		return value;
	}
}